//-------------------------------------------------------------------
//	Copyright (c) 2010-2012  Zhirnov Andrey
//	This file is part of the "UXGEN" project.
//	See copyright notice in "Engine.h".
//-------------------------------------------------------------------

#ifndef _UX_ENGINE_TYPES_H
#define _UX_ENGINE_TYPES_H

#include "../Defines/Defines.h"
#include "../Enums/Enums.h"

namespace Engine
{
namespace UXTypes
{

	//
	// Render Init Params
	//

	struct TRenderInitParams
	{
		uint		uPixelFormat;		// pixel format number
		uint8		uMSAASamples,		// Multisample Anti-Aliasing samples count (1..32)
					uColorSamples,		// Color Samples for CSAA (1..16)
					uCSAASamples,		// Coverage Samples (1..32)
					uColorDepth,
					uZBufferDepth,
					uStencilDepth;
		///
		explicit
		TRenderInitParams(	uint8	u_colors		= 32,
							uint8	u_zdepth		= 24,
							uint8	u_stencil		= 0,
							uint8	u_msaa			= 0,
							uint8	u_csaa			= 0,
							uint8	u_color_samples	= 0	):
			uMSAASamples(u_msaa), uColorSamples(u_color_samples), uCSAASamples(u_csaa),
			uColorDepth(u_colors), uZBufferDepth(u_zdepth), uStencilDepth(u_stencil),
			uPixelFormat(0) {}

		explicit
		TRenderInitParams(uint u_pixel_format):
			uPixelFormat(u_pixel_format),
			uMSAASamples(0), uColorSamples(0), uCSAASamples(0),
			uColorDepth(0), uZBufferDepth(0), uStencilDepth(0) {}
	};


	//
	// Render Params
	//

	struct TRenderParams
	{
		ivec2				sWinPos;
		ivec2				sWinSize;
		e_window_mode::type	eMode;
		uint				uFreq;
		bool				bVSync;
		bool				bFullScreen;
		///
		explicit
		TRenderParams(	const ivec2	&	s_win_size	= ( ivec2(640,480) ),
						const ivec2	&	s_win_pos	= ( ivec2() ),
						bool				b_fullscr	= false,
						bool				b_vsync		= false,
						e_window_mode::type	e_win_mode	= e_window_mode::DEF_WINDOWED,
						uint				u_freq		= 0 ):
			bVSync(b_vsync), bFullScreen(b_fullscr), sWinSize(s_win_size), sWinPos(s_win_pos),
			eMode(e_win_mode), uFreq(u_freq) {}
	};


	//
	// Sound Init Params
	//

	struct TAudioInitParams
	{
		string	sAudioDevice;
		uint	uAUXSlots;
		///
		explicit
		TAudioInitParams(const char *audio_device = nullptr, uint slots = 4):
			sAudioDevice(audio_device), uAUXSlots(slots) {}
	};


	//
	// OpenCL Init Params
	//

	struct TOpenCLInitParams
	{
		string	sDeviceName;
		bool	bShareWithGL;
		///
		explicit
		TOpenCLInitParams(	const char *	p_opencl_device	= nullptr,
							bool			b_share_with_gl	= true ):
			sDeviceName(p_opencl_device), bShareWithGL(b_share_with_gl) {}
	};


	//
	// Engine Extended Params
	//

	struct TEngExtParams
	{
		string					sResDirectory;
		e_log_msg::type			eLogFilter;
		e_resman_flags::type	eResManFlags;
		uint8					uLogLevel;
		///
		TEngExtParams():
			sResDirectory("data"), eResManFlags(e_resman_flags::FREE_NON_REF | e_resman_flags::SET_DEFAUL_RES),
			eLogFilter(e_log_msg::FILTER_ALL), uLogLevel(16) {}
	};


	//
	// Engine Init Params
	//

	struct TEngInitParams
	{
		void				*	pHandle,	// HWND for Windows, ... for Linux, could be NULL if need create window
							*	pIcon;		// HICON for Windows
		string					sClassName,
								sApplicationName;
		uint					uLoadThreads,
								uRenderThreads,
								uWindows;
		TRenderParams			sRenParams;
		TRenderInitParams		sRenInit;
		TAudioInitParams		sAudioParams;
		TOpenCLInitParams		sCLInit;
		TEngExtParams			sExtParams;
		e_eng_init_flags::type	eFlags;
		///
		explicit
		TEngInitParams( const char				*	p_app_name		= nullptr,
						const TRenderParams		&	s_rparams		= TRenderParams(),
						const TRenderInitParams	&	s_ren_init		= TRenderInitParams(),
						const TAudioInitParams	&	s_audio_init	= TAudioInitParams(),
						const TOpenCLInitParams	&	s_cl_init		= TOpenCLInitParams(),
						const TEngExtParams		&	s_ext_params	= TEngExtParams(),
						e_eng_init_flags::type		e_flags			= e_eng_init_flags::DEF_GL4,
						uint						u_load_threads	= 0,
						uint						u_render_threads= 0,
						uint						u_windows		= 0,
						void					*	p_handle		= nullptr,
						void					*	p_icon			= nullptr,
						const char				*	p_class_name	= nullptr ):
			pHandle(p_handle), sClassName(p_class_name), sApplicationName(p_app_name), sRenParams(s_rparams),
			pIcon(p_icon), eFlags(e_flags), sRenInit(s_ren_init), sAudioParams(s_audio_init),
			uLoadThreads(u_load_threads), sCLInit(s_cl_init), sExtParams(s_ext_params),
			uRenderThreads(u_render_threads), uWindows(u_windows)
		{}
	};



	//
	// Date
	//

	struct TDate
	{
		uint16	uYear,
				uMonth,
				uDayOfWeek,
				uDay,
				uHour,
				uMinute,
				uSecond,
				uMilliseconds;
		///
		TDate():
			uYear(0), uMonth(0), uDayOfWeek(0), uDay(0),
			uHour(0), uMinute(0), uSecond(0), uMilliseconds(0) {}

		void Update()
		{
			static const uint	s_aMonthDays[24] = {
				31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
				31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31		// leap year
			};

			uYear		  += uMonth			/ 12;
			
			const uint	u_month_days = ((uYear & 0x3) == 0 && uYear % 100 != 0) + uMonth;

			uMonth		  += uDay			/ u_month_days;
			uDayOfWeek	  += uDay;
			uDay		  += uHour			/ 24;
			uMinute		  += uSecond		/ 60;
			uSecond		  += uMilliseconds	/ 1000;

			uMonth		  %= 12;
			uDayOfWeek	  %= 7;
			uDay		  %= u_month_days;
			uHour		  %= 24;
			uMinute		  %= 60;
			uSecond		  %= 60;
			uMilliseconds %= 1000;
		}
	};



	//
	// System Information
	//

	struct TSystemInfo
	{
		struct TVideoCard
		{
			string				sName;
			uint				uVRAM;		// Mb
			e_gpu_model::type	eGPUModel;
			///
			TVideoCard(): uVRAM(0), eGPUModel(e_gpu_model::UNKNOWN) {}
		};

		struct TProcessor
		{
			string				sName;
			uint				uFreq;		// MHz
			uint8				uNumCores;
			///
			TProcessor(): uFreq(0), uNumCores(0) {}
		};

		array< TVideoCard >		aGPUs;
		array< TProcessor >		aCPUs;
		string					sOSName;
		uint					uRAM,			// Mb
								uVirtualMemory;	// Mb
		bool					bIs64bit;		// 32 or 64 bit OS
		///
		TSystemInfo(): uRAM(0), uVirtualMemory(0), bIs64bit(false) {}
	};



	//
	// Screen Mode
	//

	struct TScreenMode
	{
		uvec2		sResolution;
		uint		uColorDepth,
					uFrequency;
		///
		TScreenMode(const uvec2 &res, uint color, uint freq):
			sResolution(res), uColorDepth(color), uFrequency(freq) {}

		bool operator == (const TScreenMode &right)
		{
			return( All( sResolution == right.sResolution ) &&
					uColorDepth == right.uColorDepth &&
					uFrequency  == right.uFrequency );
		}

		bool operator != (const TScreenMode &right)
		{
			return !( *this == right );
		}
	};

//-------------------------------------------------------------------

}	// UXTypes
}	// Engine

#endif	// _UX_ENGINE_TYPES_H